﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ECommon
{
    /// <summary>
    /// 文件操作工具
    /// </summary>
    public static partial class FileTool
    {

        /// <summary>
        /// 将文本内容批次写入文件，不独占文件，文件追加
        /// </summary>
        /// <param name="textStr">文本内容</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="coding">编码模式，默认utf8</param>
        /// <exception cref="ArgumentNullException">入参为空异常</exception>
        public static void Append(string textStr, string filePath, Encoding coding = null)
        {
            if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(textStr))
            {
                throw new ArgumentNullException("filePath 或 textStr", "文件路径或文本为空");
            }
            ValidAndCreateDir(filePath);
            if (coding == null)
            {
                coding = Encoding.UTF8;
            }
            int batchLength = 1024 * 1024 / 8;
            int strLength = textStr.Length;
            int left = strLength % batchLength;
            int batchQty = 0;
            if (left == 0)
            {
                batchQty = strLength / batchLength;
            }
            else
            {
                batchQty = strLength / batchLength + 1;
            }
            using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
            {
                for (int i = 0; i < batchQty; i++)
                {
                    int start = i * batchLength;
                    int end = ((i + 1) * batchLength) > strLength ? strLength - start : batchLength + start;
                    string batchStr = textStr.Substring(start, end - start);
                    byte[] batchBytes = coding.GetBytes(batchStr);
                    fs.Write(batchBytes, 0, batchBytes.Length);
                }
            }
        }

        /// <summary>
        /// 将文本内容批次写入文件，不独占文件，文件覆盖
        /// </summary>
        /// <param name="textStr">文本内容</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="coding">编码模式，默认utf8</param>
        /// <exception cref="ArgumentNullException">入参为空异常</exception>
        public static void Write(string textStr, string filePath, Encoding coding = null)
        {
            if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(textStr))
            {
                throw new ArgumentNullException("filePath 或 textStr", "文件路径或文本为空");
            }
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            ValidAndCreateDir(filePath);
            if (coding == null)
            {
                coding = Encoding.UTF8;
            }
            int batchLength = 1024 * 1024 / 8;
            int strLength = textStr.Length;
            int left = strLength % batchLength;
            int batchQty = 0;
            if (left == 0)
            {
                batchQty = strLength / batchLength;
            }
            else
            {
                batchQty = strLength / batchLength + 1;
            }
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
            {
                for (int i = 0; i < batchQty; i++)
                {
                    int start = i * batchLength;
                    int end = ((i + 1) * batchLength) > strLength ? strLength - start : batchLength + start;
                    string batchStr = textStr.Substring(start, end - start);
                    byte[] batchBytes = coding.GetBytes(batchStr);
                    fs.Write(batchBytes, 0, batchBytes.Length);
                }
            }
        }

        /// <summary>
        /// 读取文件内容，不独占文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="coding">编码模式，默认utf8</param>
        /// <returns>读取的文本</returns>
        /// <exception cref="ArgumentNullException">入参为空异常</exception>
        /// <exception cref="FileNotFoundException">文件不存在异常</exception>
        public static string Read(string filePath, Encoding coding = null)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath", "文件路径为空");
            }
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("文件不存在", filePath);
            }
            if (coding == null)
            {
                coding = Encoding.UTF8;
            }
            int batchLength = 1024 * 1024;
            byte[] batchBytes = new byte[batchLength];
            int contentLength = 0;
            List<byte> totalBytes = new List<byte>();
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                do
                {
                    contentLength = fs.Read(batchBytes, 0, batchLength);
                    totalBytes.AddRange(batchBytes.Take(contentLength));
                }
                while (contentLength >= batchLength);
            }
            return coding.GetString(totalBytes.ToArray());
        }

        /// <summary>
        /// 验证文件夹目录，如果目录不存在则创建
        /// </summary>
        /// <param name="fullFilePathWithExt">含拓展名的文件全路径</param>
        public static void ValidAndCreateDir(string fullFilePathWithExt)
        {
            string fileDir = Path.GetDirectoryName(fullFilePathWithExt);
            if (!Directory.Exists(fileDir))
            {
                Directory.CreateDirectory(fileDir);
            }
        }

        /// <summary>
        /// 创建路径的目录
        /// </summary>
        /// <param name="path">路径</param>
        public static void CreateDirectory(string path)
        {
            string fullPath = Path.GetFullPath(path);
            string directory = Path.GetDirectoryName(fullPath);
            if (string.IsNullOrEmpty(directory))
            {
                return;
            }
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
        }

        /// <summary>
        /// 验证文件是否存在
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <exception cref="ArgumentNullException">参数为空异常</exception>
        /// <exception cref="FileNotFoundException">文件不存在异常</exception>
        public static void FmtFilePathAndExistCheck(ref string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath", "文件路径为空");
            }
            filePath = filePath.Replace('\\', Path.DirectorySeparatorChar);
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("文件不存在", filePath);
            }
        }

        /// <summary>
        /// 判定一个字符串是否是一个目录
        /// </summary>
        /// <param name="path">字符串</param>
        /// <returns>判定结果</returns>
        public static bool IsDir(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return false;
            }
            if (!Directory.Exists(path))
            {
                string[] pathParts = path.Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
                if (pathParts == null || pathParts.Length <= 0)
                {
                    return false;
                }
                else
                {
                    return !pathParts[pathParts.Length - 1].Contains(".");
                }
            }
            return true;
        }

        /// <summary>
        /// 判定一个字符串是否是一个文件路径
        /// </summary>
        /// <param name="path">字符串</param>
        /// <returns>判定结果</returns>
        public static bool IsFilePath(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return false;
            }
            if (!File.Exists(path))
            {
                string[] pathParts = path.Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
                if (pathParts == null || pathParts.Length <= 0)
                {
                    return false;
                }
                else
                {
                    return pathParts[pathParts.Length - 1].Contains(".");
                }
            }
            return true;
        }
    }
}
